package com.tencreat.service.system.impl;


import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.lock.annotation.Lock4j;
import com.tencreat.common.config.SMSConfig;
import com.tencreat.common.core.redis.RedisCache;
import com.tencreat.common.enums.account.CitySmsTypeEnum;
import com.tencreat.common.enums.mall.AllEnum;
import com.tencreat.common.exception.CustomException;
import com.tencreat.common.utils.DictUtils;
import com.tencreat.common.utils.StringUtils;
import com.tencreat.common.utils.TenCreatUtil;
import com.tencreat.common.utils.http.HttpUtils;
import com.tencreat.common.utils.sign.Md5Utils;
import com.tencreat.common.utils.spring.SpringUtils;
import com.tencreat.domain.account.AccountLoginCheck;
import com.tencreat.domain.account.dto.ShopOpenSendCodeDTO;
import com.tencreat.domain.account.vo.ResSmsResultVO;
import com.tencreat.service.account.IAccountLoginCheckService;
import com.tencreat.service.system.ISysMessageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/***
 * 三方短信实现
 */
@Slf4j
@Service
@Configuration
@ConditionalOnProperty(prefix = "sys.message", name = "impl", havingValue = "aspx")
@RequiredArgsConstructor
public class SysAspxMessageServiceImpl implements ISysMessageService {

    private final RedisCache redisCache;

    /*****
     * 发送验证码
     * @param openSendCodePO
     * @return
     */
    @Lock4j(keys = "#openSendCodePO.phone")
    @Override
    public void sendSMS(ShopOpenSendCodeDTO openSendCodePO) {
        // 是否重复发送
        String cacheKey2 = TenCreatUtil.getSmsCodeCacheKey2(openSendCodePO.getPhone());
        if (redisCache.hasKey(cacheKey2)) {
            throw new CustomException("请勿重复获取，稍后再试");
        }
        redisCache.setCacheObject(cacheKey2, 1, 40, TimeUnit.SECONDS);

        // 已注册用户不发验证码
        if (openSendCodePO.getType() == CitySmsTypeEnum.REGISTERED) {
            int count = SpringUtil.getBean(IAccountLoginCheckService.class).lambdaQuery().eq(AccountLoginCheck::getPhone, openSendCodePO.getPhone()).count();
            if (count > 0) {
                throw new CustomException("已经注册");
            }
        }

        // 发送验证码短信
        String code = TenCreatUtil.getRandomNumCode(4);
        String result = sms(openSendCodePO.getPhone(), "您的验证码是:" + code);

        // 验证码key存redis
        if (StringUtils.isNotEmpty(result)) {
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getString("resultCode").equals("1")) {
                String cacheKey = TenCreatUtil.getSmsCodeCacheKey(openSendCodePO.getType(), openSendCodePO.getPhone());
                redisCache.setCacheObject(cacheKey, code, 300, TimeUnit.SECONDS);
                return;
            }
            throw new CustomException(jsonObject.getString("resultMsg"));
        } else {
            throw new CustomException("发送短信失败");
        }
    }

    @Override
    public void verifySmsCode(CitySmsTypeEnum type, String phone, String code) {
        String SUPER_CODE = DictUtils.getDictValue("code_config","super_code");
        // 超级验证码是否有效 0-无效
        String status = DictUtils.getDictValue("code_config","status");
        // 非正式环境，超级验证码免校验
        if (code.equals(SUPER_CODE) && status.equals("0")) {
            throw new CustomException("验证码错误");
        }

        // 校验验证码
        String cacheKey = TenCreatUtil.getSmsCodeCacheKey(type, phone);
        String redisCode = redisCache.getCacheObject(cacheKey);
        if (!code.equals(redisCode) && !code.equals(SUPER_CODE)) {
            throw new CustomException("验证码错误");
        }

        // 删除正确的验证码
        redisCache.deleteObject(cacheKey);
    }

    @Override
    public void auditMallSupplier(String phone, String conent) {
        sms(phone, conent);
    }

    @Override
    public void smsSupplierApproved(String phone, String userName, String password) {
        String sendMsg = "你的供应商入驻申请已审核通过，账号：{},密码：{},供应商后台管理链接为:"+DictUtils.getDictValue("sys_message_website","supplier");;
        sendMsg = StrUtil.format(sendMsg, userName, password);
        sms(phone, sendMsg);
    }



    @Override
    public void auditMallStore(String phone, String conent) {
        sms(phone, conent);
    }

    @Override
    public void smsStoreApproved(String phone, String userName, String password) {
        String sendMsg = "你的店铺入驻申请已审核通过，账号：{},密码：{},店铺后台管理链接为:"+DictUtils.getDictValue("sys_message_website","mallStore");;
        sendMsg = StrUtil.format(sendMsg, userName, password);
        sms(phone, sendMsg);
    }

    @Override
    public void pushMessage(String phone, String conent) {
        sms(phone, conent);
    }

    /******
     *
     * @param phone 手机号
     * @param content 发送内容  自动添加短信签名，
     */
    private String sms(String phone, String content) {
        if (StringUtils.isEmpty(content)) {
            log.info("发送短信失败， 短信内容为空");
            return "";
        }
        SMSConfig smsConfig = SMSConfig.getSMSConfig();
        smsConfig.setContent(content + smsConfig.getSignature());

        Map<String, String> params = new HashMap<>();
        params.put("password", smsConfig.getPassword());
        params.put("mobile", phone);
        params.put("userName", smsConfig.getAccount());
        params.put("sign", Md5Utils.hash(smsConfig.getAccount() + smsConfig.getPassword() + phone + smsConfig.getContent()));
        params.put("content", smsConfig.getContent());

        log.info("发送短信请求：" + JSONObject.toJSONString(params));
        String result = HttpUtils.sendPostV2(smsConfig.getSendUrl(), JSONObject.toJSONString(params));
        log.info("发送短信结果：" + result);
        return result;
    }

}
